package com.business.redis.utils;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis 操作类
 */
@Component
public class RedisUtil {

    private static RedisTemplate<String, Object> redisTemplate;


    private static final Logger logger = LoggerFactory.getLogger(RedisUtil.class);

    //----------String---------////
    public static Object getValue(String redisKey) {
        try {
            return redisTemplate.opsForValue().get(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public static void setValue(String redisKey, Object obj) {
        try {
            redisTemplate.opsForValue().set(redisKey, obj);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    public static Boolean setIfAbsent(String redisKey, Object obj) {
        try {
            return redisTemplate.opsForValue().setIfAbsent(redisKey, obj);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return false;
    }

    public static Boolean setIfAbsent(String redisKey, Object obj, long time) {
        try {
            return redisTemplate.opsForValue().setIfAbsent(redisKey, obj, time, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return false;
    }

    /**
     * 设置过期时间
     *
     * @param redisKey
     * @param obj
     * @param time     毫秒数
     */
    public static void setValue(String redisKey, Object obj, long time) {
        try {
            redisTemplate.opsForValue().set(redisKey, obj);
            redisTemplate.expire(redisKey, time, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 获取value 并且转换
     *
     * @param redisKey
     * @return
     */
    public static Object getObject(String redisKey, Class cls) {
        try {
            Object object = redisTemplate.opsForValue().get(redisKey);
            if (object == null) {
                return null;
            }
            return JSON.parseObject(object.toString(), cls);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取value 并且转换
     *
     * @param redisKey
     * @param cls
     * @return list
     */
    public static List getArray(String redisKey, Class cls) {
        try {
            return JSON.parseArray(redisTemplate.opsForValue().get(redisKey).toString(), cls);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }
    //----------hash---------////

    /**
     * 获取所有元素
     *
     * @param redisKey
     * @return
     */
    public static List getHashValues(String redisKey) {
        try {
            return redisTemplate.opsForHash().values(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public static Set getHashKeys(String redisKey) {
        try {
            return redisTemplate.opsForHash().keys(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public static Object getHashValue(String redisKey, String hashKey) {
        try {
            return redisTemplate.opsForHash().get(redisKey, hashKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public static Object getHashObject(String redisKey, String hashKey, Class cls) {
        try {
            return JSON.parseObject(redisTemplate.opsForHash().get(redisKey, hashKey).toString(), cls);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public static void setHashValue(String redisKey, String hashKey, Object object) {
        try {
            redisTemplate.opsForHash().put(redisKey, hashKey, object);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    public static void setHashValue(String redisKey, String hashKey, Object object, long time) {
        try {
            redisTemplate.opsForHash().put(redisKey, hashKey, object);
            redisTemplate.expire(redisKey, time, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 判断hash 是否存在key
     *
     * @param redisKey
     * @param hashKey
     */
    public static void hasHashKey(String redisKey, String hashKey) {
        try {
            redisTemplate.opsForHash().hasKey(redisKey, hashKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 删除hash 元素
     *
     * @param redisKey
     * @param hashKey
     */
    public static void delHashValue(String redisKey, String hashKey) {
        try {
            redisTemplate.opsForHash().delete(redisKey, hashKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

    }
    //----------set---------////

    /**
     * 获取所有元素
     *
     * @param redisKey
     * @return
     */
    public static Set getSetValues(String redisKey) {
        try {
            return redisTemplate.opsForSet().members(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 添加set元素
     *
     * @param redisKey
     * @return
     */
    public static Long addSetValue(String redisKey, Object... object) {
        try {
            return redisTemplate.opsForSet().add(redisKey, object);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 删除set元素
     *
     * @param redisKey
     * @return
     */
    public static Long removeSetValue(String redisKey, Object... object) {
        try {
            return redisTemplate.opsForSet().remove(redisKey, object);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取set长度
     *
     * @param redisKey
     * @return
     */
    public static Long getSetSize(String redisKey) {
        try {
            return redisTemplate.opsForSet().size(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }
    //----------zSet---------////

    /**
     * 获取所有元素
     *
     * @param redisKey
     * @return
     */
    public static Set getZSetValues(String redisKey, long beginIndex, long endIndex) {
        try {
            return redisTemplate.opsForZSet().range(redisKey, beginIndex, endIndex);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 添加set元素
     *
     * @param redisKey
     * @return
     */
    public static boolean addZSetValue(String redisKey, Object object, double score) {
        try {
            return redisTemplate.opsForZSet().add(redisKey, object, score);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return false;
    }

    /**
     * 获取set长度
     *
     * @param redisKey
     * @return
     */
    public static Long getZSetSize(String redisKey) {
        try {
            return redisTemplate.opsForZSet().size(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 删除元素
     *
     * @param redisKey
     * @return
     */
    public static Long removeZSet(String redisKey, Object object) {
        try {
            return redisTemplate.opsForZSet().remove(redisKey, object);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 删除元素
     *
     * @param redisKey
     * @return
     */
    public static Long removeZSetByScore(String redisKey, double score1, double score2) {
        try {
            return redisTemplate.opsForZSet().removeRangeByScore(redisKey, score1, score2);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 添加分数
     *
     * @param redis
     * @param key
     * @param score
     * @return
     */
    public static Long incrementScore(String redis, String key, double score) {
        try {
            redisTemplate.opsForZSet().incrementScore(redis, key, score);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public static Set<Object> reverseRangeByScore(String redis, double min, double max) {
        try {
           return redisTemplate.opsForZSet().reverseRangeByScore(redis, min, max);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }


    //----------list---------////

    /**
     * 获取所有元素
     *
     * @param redisKey
     * @return
     */
    public static List getListValues(String redisKey) {
        try {
            return redisTemplate.opsForList().range(redisKey, 0, -1);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取元素
     *
     * @param redisKey
     * @return
     */
    public static List getListValues(String redisKey, int begin, int end) {
        try {
            return redisTemplate.opsForList().range(redisKey, begin, end);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 弹出元素
     *
     * @param redisKey
     * @return
     */
    public static Object popListValue(String redisKey) {
        try {
            return redisTemplate.opsForList().leftPop(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }


    /**
     * 压入元素
     *
     * @param redisKey
     * @param value
     */
    public static void pushListValue(String redisKey, Object value) {
        try {
            redisTemplate.opsForList().leftPush(redisKey, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 设置长度，截取一部分
     *
     * @param redisKey
     * @param begin
     * @param end
     */
    public static void trimList(String redisKey, long begin, long end) {
        try {
            redisTemplate.opsForList().trim(redisKey, begin, end);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 移除
     *
     * @param redisKey
     * @param value
     * @return
     */
    public static Long removeList(String redisKey, Object value) {
        try {
            return redisTemplate.opsForList().remove(redisKey, 1, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return 0L;
    }

    /**
     * 获取总长度
     *
     * @param redisKey
     * @return
     */
    public static Long getListSize(String redisKey) {
        try {
            return redisTemplate.opsForList().size(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return 0L;
    }


    //----------通用---------////

    /**
     * 删除key
     *
     * @param redisKey
     */
    public static boolean delValue(String redisKey) {
        try {
            return redisTemplate.delete(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return false;
    }

    /**
     * 批量删除key
     *
     * @param pattern
     */
    @SuppressWarnings("unchecked")
    public static void delValuePattern(String pattern) {
        try {
            Set<String> keys = redisTemplate.keys(pattern);
            if (keys.size() > 0) {
                redisTemplate.delete(keys);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

    }

    /**
     * 获取所有的key
     *
     * @param pattern
     * @return
     */
    public static Set<String> keys(String pattern) {
        try {
            Set<String> keys = redisTemplate.keys(pattern);
            return keys;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 批量删除
     *
     * @param keys
     * @return
     */
    public static Long delValue(Collection<String> keys) {
        try {
            return redisTemplate.delete(keys);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return 0L;

    }

    /**
     * 设置过期时间
     *
     * @param redisKey
     * @param time
     * @return
     */
    public static boolean expire(String redisKey, long time) {
        try {
            return redisTemplate.expire(redisKey, time, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return false;
    }


    /**
     * 判断key是否存在
     *
     * @param redisKey
     * @return
     */
    public static boolean hasKey(String redisKey) {
        try {
            return redisTemplate.hasKey(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return false;
    }

    /**
     * 添加增量
     *
     * @param redisKey
     * @return
     */
    public static Long incr(String redisKey) {
        try {
            return redisTemplate.opsForValue().increment(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return 0L;
    }

    /**
     * 减少增量
     *
     * @param redisKey
     * @return
     */
    public static Long decr(String redisKey) {
        try {
            return redisTemplate.opsForValue().decrement(redisKey);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return 0L;
    }

    @Resource(name = "jsonRedisTemplate")
    public void setRedisTemplate(RedisTemplate<String, Object> r) {
        redisTemplate = r;
    }


}
